package zhanglu.family.socket.textline.busclient;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import zhanglu.family.socket.bean.ErrMsg;
import zhanglu.family.socket.bean.busbean.BusHeadBean;
import zhanglu.family.socket.bean.busbean.BusMsgBean;
import zhanglu.family.socket.bean.busbean.BusPostAnnotation;
import zhanglu.family.socket.util.JsonUtil;

/**
 * 客户端消息处理
 * 
 * @author zhanglu
 * @date 2016-09-18
 * @description 以下介绍了全部7个方法，各有用途
 */
public class BusClientHandler extends IoHandlerAdapter {

    private BusTCPClient       client;                                       // 客户端
    private String              methodName    = "messageReceived";            // 方法名称，实现了异步消息统一接口
    private Map<Long, Class<?>> classMap      = new HashMap<Long, Class<?>>(); // 存放异步消息接解析类的类路径以及headId,key为headId,val为类路径
    private boolean             isSynchronize = false;                        // 是否同步，true同步，false异步

    /**
     * 实例化客户端对象
     * 
     * @param client
     *            客户端
     * @param classPath
     *            类路径的数组
     * @param isSynchronize
     *            是否同步，true同步，false异步
     * @throws Exception
     */
    public BusClientHandler(BusTCPClient client, List<String> classPath, boolean isSynchronize) throws Exception {
        this.client = client;
        this.isSynchronize = isSynchronize;

        if (null != classPath) {
            for (String path : classPath) {
                Class<?> classz = Class.forName(path);
                BusPostAnnotation post = classz.getAnnotation(BusPostAnnotation.class);
                classMap.put(post.headId(), classz);
            }
        }

    }

    /**
     * sessionCreated:当一个新的连接建立时，由I/O processor thread调用；
     * 
     */
    @Override
    public void sessionCreated(IoSession session) throws Exception {

    }

    /**
     * sessionOpened:当连接打开是调用
     */
    @Override
    public void sessionOpened(IoSession session) throws Exception {

    }

    /**
     * messageReceived:当接收了一个消息时调用,这个也是最重要的
     */
    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        BusMsgBean msg = (BusMsgBean) JsonUtil.StringToOb(message, BusMsgBean.class);
        
        BusHeadBean bean = msg.getHead();

        BusMsgBean resultMsg = client.synMsgMap.get(bean.getSeqId());// 获取同步对象
        if (null != resultMsg && resultMsg.getErrMsg() == ErrMsg.WAIT) {// 如果能获取同步map并且处于等待状态，说明发送的同步消息。
            client.synMsgMap.put(bean.getSeqId(), msg);
        } else {
            long headId = bean.getHeadId();// 获取业务id

            Class<?> classz = classMap.get(headId);// 获取对应的异步消息解析类
            Object ob = classz.newInstance();
            Method me = classz.getMethod(methodName, BusMsgBean.class);
            me.invoke(ob, msg);// 反射
        }

    }

    /**
     * messageSent：当一个消息被(IoSession#write)发送出去后调用
     */
    @Override
    public void messageSent(IoSession session, Object message) throws Exception {

    }

    /**
     * sessionIdle:当连接进入空闲状态时调用,同步消息可重写后方法清空
     */
    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        if (!isSynchronize) {
            super.sessionClosed(session);
        }
    }

    /**
     * sessionClosed:当连接关闭时调用,同步消息可重写后方法清空
     */
    @Override
    public void sessionClosed(IoSession session) throws Exception {
        if (!isSynchronize) {
            client.reconnection();
        }
    }

    /**
     * exceptionCaught:当实现IoHandler的类抛出异常时调用,同步消息可重写后方法清空
     */
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        if (!isSynchronize) {
            super.sessionClosed(session);
        }
    }
}
